package till;

import java.util.HashMap;
import java.util.Map;


public class TagBuilder {
	/**
	 * Wzorzec atrybutu taga
	 */
	private static final String ATTRIBUTES_TEMPLATE = "%s=\"%s\"";

	
	/**
	 * Atrybuty taga
	 */
	private Map<String, Object> attributes = new HashMap<String, Object>();

	/**
	 * Zbior tagow zagniezdzonych
	 */
	private Map<String, TagBuilder> nestedTags = new HashMap<String, TagBuilder>();

	private Boolean selfClosing = true;

	private StringBuilder tag = new StringBuilder("");

	private String tagName;

	/**
	 * Podstawowy konstruktor
	 * 
	 * @param tagName
	 */
	private TagBuilder(String tagName) {
		this.tagName = tagName;
	}

	/**
	 * Dodaje do taga inny tag zagniezdzony, np<br />
	 * <code>
	 * &lt;tagName&gt;<br />
	 * &lt;nestedTagName /&gt;<br />
	 * &lt;/tagName&gt;
	 * </code>
	 * 
	 * @return <b>this</b>
	 */
	public TagBuilder addNestedTag(TagBuilder builder) {
		nestedTags.put(builder.tagName, builder);
		return this;
	}

	/**
	 * Buduje tag
	 * 
	 * @return stringowa reprezentacja taga
	 */
	public String build() {
		tag.append("<" + tagName);

		// add attributes
		for (String name : attributes.keySet()) {
			tag.append(" ");
			tag.append(String.format(ATTRIBUTES_TEMPLATE, name,
					attributes.get(name)));
		}

		if (selfClosing) {
			tag.append(" />");
		} else {
			tag.append(">");

			// add nestedTags
			for (String name : nestedTags.keySet()) {
				tag.append("\n");
				tag.append(nestedTags.get(name).build());
			}

			tag.append("\n</" + tagName + ">");

		}

		return tag.toString();

	}


	/**
	 * Czy tag ma byc samozamykajacy
	 * 
	 * @param selfClosng
	 * @return <b>this</b>
	 */
	public TagBuilder selfClosing(Boolean selfClosng) {
		this.selfClosing = selfClosng;
		return this;
	}

	/**
	 * Ustawia atrybut taga, np <code>&lt;nazwaTaga name="value" /&gt;</code>
	 * 
	 * @param name
	 *            nazwa atrybutu
	 * @param value
	 *            wartosc
	 * @return <b>this</b>
	 */
	public TagBuilder setAttribute(String name, Object value) {
		attributes.put(name, value);

		return this;
	}

	@Override
	public String toString() {
		return tag.toString();
	}
	
	/**
	 * Tworzy stadnardowy builder taga
	 * @param tagName
	 * @return
	 */
	public static  TagBuilder createDefaultTagBuilder(String tagName) {
		return new TagBuilder(tagName);
		
	}

}
